﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Entities;
using System.Data.SqlClient;
using System.Data;

namespace AccesoDatos
{
    public class Facturas
    {
        public static void registrarFactura(Factura f, List<Detalle_Factura> listDF, out int filasAfectadas)
        {
            filasAfectadas = 0;
            int cantInsertFactura = 0;
            int cantInsertDetallesF = 0;
            int filasUpdate = 0;

            if (listDF.Count > 0)
            {
                //alta
                SqlConnection conexion = DB.Conectar();
                SqlTransaction trans = null;
                try
                {
                    trans = conexion.BeginTransaction();

                    //crear factura
                    string cmdFactura = "Insert INTO Factura (fechaEmision, idCliente, idEstadoFactura) VALUES (@fechaEmision,@idCliente,@idEstadoFactura)";
                    List<SqlParameter> listaParam = new List<SqlParameter>();
                    listaParam.Add(new SqlParameter("@fechaEmision", f.FechaEmision));
                    listaParam.Add(new SqlParameter("@idCliente", f.IdCliente));
                    listaParam.Add(new SqlParameter("@idEstadoFactura", f.IdEstadoFactura));
                    cantInsertFactura = DB.EjecutarCommand(cmdFactura, listaParam, conexion, trans);

                    //obtener idFactura
                    string cmdIDFactura = "Select @@identity FROM Factura";
                    listaParam = new List<SqlParameter>();
                    int idFactura = int.Parse(DB.EjecutarScalar(cmdIDFactura, listaParam, conexion, trans));


                    //cargar detalles
                    if (cantInsertFactura > 0)
                    {
                        foreach (Detalle_Factura itemDF in listDF)
                        {
                            string comando = "INSERT INTO Detalle_Factura (idFactura, idProducto, cantidad, precioUnitario) VALUES (@idFactura,@idProducto,@cantidad,@precioUnitario)";
                            List<SqlParameter> lstParametros = new List<SqlParameter>();
                            lstParametros.Add(new SqlParameter("@idFactura", idFactura));
                            lstParametros.Add(new SqlParameter("@idProducto", itemDF.IdProducto));
                            lstParametros.Add(new SqlParameter("@cantidad", itemDF.Cantidad));
                            lstParametros.Add(new SqlParameter("@precioUnitario", itemDF.PrecioUnitario));
                            cantInsertDetallesF = DB.EjecutarCommand(comando, lstParametros, conexion, trans);
                        }

                        if (cantInsertDetallesF > 0)
                        {
                            int nuevoStock = 0;
                            int stockActual = 0;
                            foreach (Detalle_Factura item in listDF)
                            {
                                stockActual = Productos.ObtenerStockProducto(item.IdProducto);
                                nuevoStock = stockActual - item.Cantidad;

                                string comando = "UPDATE Producto SET stock = @stock WHERE (idProducto = @idProducto)";
                                List<SqlParameter> lstParametros = new List<SqlParameter>();
                                lstParametros.Add(new SqlParameter("@stock", nuevoStock));
                                lstParametros.Add(new SqlParameter("@idProducto", item.IdProducto));
                                filasUpdate = DB.EjecutarCommand(comando, lstParametros, conexion, trans);
                            }
                            if (filasUpdate > 0)
                            {
                                filasAfectadas = filasUpdate;
                                trans.Commit();
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    if (trans != null)
                        trans.Rollback();
                    throw new Exception("No se pudo registrar la factura " + ex.Message);
                }
                finally
                {
                    if (conexion != null && conexion.State == ConnectionState.Open)
                        conexion.Close();
                }

            }
        }
        public List<Factura> obtenerFacturasPorFecha(DateTime? fechaDesde, DateTime? fechaHasta)
        {
            SqlConnection conexion = null;
            List<Factura> lstFacturas = null;
            try
            {
                if (fechaDesde == null && fechaHasta == null)
                {
                    lstFacturas = null;
                }
                else
                {
                    conexion = DB.Conectar();
                    string comando = "SELECT idFactura,fechaEmision FROM Factura WHERE 1=1";
                    List<SqlParameter> lstParametros = new List<SqlParameter>();
                    if (fechaDesde != null && fechaHasta != null)
                    {
                        comando += " and fechaEmision BETWEEN @fechaDesde AND @fechaHasta";
                        lstParametros.Add(new SqlParameter("@fechaDesde", fechaDesde));
                        lstParametros.Add(new SqlParameter("@fechaHasta", fechaHasta));
                    }
                    else if (fechaDesde != null)
                    {
                        comando += " and fechaEmision >= @fechaDesde";
                        lstParametros.Add(new SqlParameter("@fechaDesde", fechaDesde));
                    }
                    else if(fechaHasta!=null)
                    {
                        comando += " and fechaEmision <= @fechaHasta";
                        lstParametros.Add(new SqlParameter("@fechaHasta", fechaHasta));
                    }
                    SqlDataReader dr = DB.GenerarReader(comando, lstParametros, conexion);
                    //List<Factura> lstFacturas = new List<Factura>();
                    lstFacturas = new List<Factura>();
                    Factura objFactura;
                    while (dr.Read())
                    {
                        objFactura = new Factura();
                        objFactura.IdFactura = (int)dr["idFactura"];
                        objFactura.FechaEmision = Convert.ToDateTime(dr["fechaEmision"]);
                        lstFacturas.Add(objFactura);
                        objFactura = null;
                    }
                    //conexion.Close();
                    //return lstFacturas;
                }
            }
            catch (SqlException ex)
            {
                //Con throw la información de la pila es mas profunda de donde se genero el error
                //En la capa de Presentación se Captura como Exception
                throw new Exception("Hubo un problema al cargar las facturas.", ex);
            }
            catch (Exception ex)
            {
                throw new Exception("Hubo un problema al cargar las facturas.", ex);
            }
            finally
            {
                if (conexion != null && conexion.State == ConnectionState.Open)
                    conexion.Close();
            }
            return lstFacturas;
        }
        public static List<Factura> ObtenerTodos()
        {
            SqlConnection conexion = null;
            List<Factura> lstFacturas = null;
            try
            {
                conexion = DB.Conectar();

                string comando = "SELECT idFactura, fechaEmision, idCliente, idEstadoFactura FROM Factura";
                List<SqlParameter> lstParametros = new List<SqlParameter>();
                SqlDataReader dr = DB.GenerarReader(comando, lstParametros, conexion);
                //List<Factura> lstFacturas = new List<Factura>();
                lstFacturas = new List<Factura>();
                Factura objFactura;
                while (dr.Read())
                {
                    objFactura = new Factura();
                    objFactura.IdFactura = (int)dr["idFactura"];
                    objFactura.FechaEmision = Convert.ToDateTime(dr["fechaEmision"]);
                    objFactura.IdCliente = Convert.ToInt32(dr["idCliente"]);
                    objFactura.IdEstadoFactura = (int)dr["idEstadoFactura"];
                    lstFacturas.Add(objFactura);
                    objFactura = null;
                }
                //conexion.Close();
            }
            catch (SqlException ex)
            {
                //Con throw la información de la pila es mas profunda de donde se genero el error
                //En la capa de Presentación se Captura como Exception
                throw new Exception("Hubo un problema al cargar las facturas.", ex);
            }
            catch (Exception ex)
            {
                throw new Exception("Hubo un problema al cargar las facturas.", ex);
            }
            finally
            {
                conexion.Close();
            }
            return lstFacturas;
        }
        public static List<Factura> ObtenerTodosPendientes()
        {
            SqlConnection conexion = null;
            List<Factura> lstFacturas = null;
            try
            {
                conexion = DB.Conectar();

                string comando = "SELECT idFactura, fechaEmision, idCliente, idEstadoFactura FROM Factura where idEstadoFactura=1";
                List<SqlParameter> lstParametros = new List<SqlParameter>();
                SqlDataReader dr = DB.GenerarReader(comando, lstParametros, conexion);
                //List<Factura> lstFacturas = new List<Factura>();
                lstFacturas = new List<Factura>();
                Factura objFactura;
                while (dr.Read())
                {
                    objFactura = new Factura();
                    objFactura.IdFactura = (int)dr["idFactura"];
                    objFactura.FechaEmision = Convert.ToDateTime(dr["fechaEmision"]);
                    objFactura.IdCliente = Convert.ToInt32(dr["idCliente"]);
                    objFactura.IdEstadoFactura = (int)dr["idEstadoFactura"];
                    lstFacturas.Add(objFactura);
                    objFactura = null;
                }
                //conexion.Close();
                //return lstFacturas;
            }
            catch (SqlException ex)
            {
                //Con throw la información de la pila es mas profunda de donde se genero el error
                //En la capa de Presentación se Captura como Exception
                throw new Exception("Hubo un problema al cargar las facturas.", ex);
            }
            catch (Exception ex)
            {
                throw new Exception("Hubo un problema al cargar las facturas.", ex);
            }
            finally
            { conexion.Close(); }
            return lstFacturas;
        }
        public static List<Factura> BuscarFacturasPorFecha(DateTime? fechaDesde, DateTime? fechaHasta)
        {
            SqlConnection conexion = null;
            List<Factura> lstFacturas = null;
            try
            {
                if (fechaDesde == null && fechaHasta == null)
                {
                    lstFacturas = null;
                }
                else
                {
                    conexion = DB.Conectar();
                    string comando = "SELECT idFactura, fechaEmision, idCliente, idEstadoFactura FROM Factura WHERE 1=1 and idEstadoFactura=1";
                    List<SqlParameter> lstParametros = new List<SqlParameter>();
                    if (fechaDesde != null && fechaHasta != null)
                    {
                        comando += " and fechaEmision BETWEEN @fechaDesde AND @fechaHasta";
                        lstParametros.Add(new SqlParameter("@fechaDesde", fechaDesde));
                        lstParametros.Add(new SqlParameter("@fechaHasta", fechaHasta));
                    }
                    else if (fechaDesde != null)
                    {
                        comando += " and fechaEmision >= @fechaDesde";
                        lstParametros.Add(new SqlParameter("@fechaDesde", fechaDesde));
                    }
                    else if(fechaHasta !=null)
                    {
                        comando += " and fechaEmision <= @fechaHasta";
                        lstParametros.Add(new SqlParameter("@fechaHasta", fechaHasta));
                    }
                    SqlDataReader dr = DB.GenerarReader(comando, lstParametros, conexion);
                    //List<Factura> lstFacturas = new List<Factura>();
                    lstFacturas = new List<Factura>();
                    Factura objFactura;
                    while (dr.Read())
                    {
                        objFactura = new Factura();
                        objFactura.IdFactura = (int)dr["idFactura"];
                        objFactura.FechaEmision = Convert.ToDateTime(dr["fechaEmision"]);
                        objFactura.IdCliente = Convert.ToInt32(dr["idCliente"]);
                        objFactura.IdEstadoFactura = (int)dr["idEstadoFactura"];
                        lstFacturas.Add(objFactura);
                        objFactura = null;
                    }
                    //conexion.Close();
                    //return lstFacturas;
                }
            }
            catch (SqlException ex)
            {
                //Con throw la información de la pila es mas profunda de donde se genero el error
                //En la capa de Presentación se Captura como Exception
                throw new Exception("Hubo un problema al cargar las facturas.", ex);
            }
            catch (Exception ex)
            {
                throw new Exception("Hubo un problema al cargar las facturas.", ex);
            }
            finally
            {
                conexion.Close();
            }
            return lstFacturas;
        }
        public static Factura BuscarPorId(int id)
        {
            SqlConnection conexion = null;
            Factura objFactura = null;
            try
            {
                conexion = DB.Conectar();

                string comando = "SELECT idFactura, fechaEmision, idCliente, idEstadoFactura FROM Factura where idFactura=@id";
                List<SqlParameter> lstParametros = new List<SqlParameter>();
                lstParametros.Add(new SqlParameter("@id", id));
                SqlDataReader dr = DB.GenerarReader(comando, lstParametros, conexion);
                //Factura objFactura = null;
                while (dr.Read())
                {
                    objFactura = new Factura();
                    objFactura.IdFactura = (int)dr["idFactura"];
                    objFactura.FechaEmision = Convert.ToDateTime(dr["fechaEmision"]);
                    objFactura.IdCliente = Convert.ToInt32(dr["idCliente"]);
                    objFactura.IdEstadoFactura = (int)dr["idEstadoFactura"];
                }
                //conexion.Close();
                //return objFactura;
            }
            catch (SqlException ex)
            {
                //Con throw la información de la pila es mas profunda de donde se genero el error
                //En la capa de Presentación se Captura como Exception
                throw new Exception("Hubo un problema al cargar la factura.", ex);
            }
            catch (Exception ex)
            {
                throw new Exception("Hubo un problema al cargar la factura.", ex);
            }
            finally
            {
                conexion.Close();
            }
            return objFactura;

        }
        public static List<Factura> ObtenerTodosInforme()
        {
            SqlConnection conexion = null;
            List<Factura> lstFacturas = null;
            try
            {
                conexion = DB.Conectar();

                string comando = "SELECT idFactura, fechaEmision, idCliente, idEstadoFactura FROM Factura";
                List<SqlParameter> lstParametros = new List<SqlParameter>();
                SqlDataReader dr = DB.GenerarReader(comando, lstParametros, conexion);
                lstFacturas = new List<Factura>();
                Factura objFactura;
                while (dr.Read())
                {
                    objFactura = new Factura();
                    objFactura.IdFactura = (int)dr["idFactura"];
                    objFactura.FechaEmision = Convert.ToDateTime(dr["fechaEmision"]);
                    objFactura.IdCliente = Convert.ToInt32(dr["idCliente"]);
                    objFactura.IdEstadoFactura = (int)dr["idEstadoFactura"];
                    lstFacturas.Add(objFactura);
                    objFactura = null;
                }
                //conexion.Close();
            }
            catch (SqlException ex)
            {
                //Con throw la información de la pila es mas profunda de donde se genero el error
                //En la capa de Presentación se Captura como Exception
                throw new Exception("Hubo un problema al cargar las facturas.", ex);
            }
            catch (Exception ex)
            {
                throw new Exception("Hubo un problema al cargar las facturas.", ex);
            }
            finally
            {
                conexion.Close();
            }
            if (lstFacturas != null && lstFacturas.Count > 0)
            {

                foreach (Factura item in lstFacturas)
                {
                    item.Cliente = Clientes.BuscarPorId(item.IdCliente).ObtenerNombreCompleto();
                    item.EstadoFactura = Estados_Facturas.BuscarPorId(item.IdEstadoFactura).Nombre;
                    item.Monto = CalcularMonto(item.IdFactura);
                    if (item.IdEstadoFactura != 1)
                    {
                        Detalle_Itinerario detIt = Detalles_Itinerario.BuscarFacturaInItinerario(item.IdFactura);
                        if (detIt != null)
                        {
                            item.IdItinerario = detIt.IdItinerario;
                            item.FechaReparto = detIt.FechaHoraEntrega;
                        }
                    }
                }
            }
            return lstFacturas;
        }
        private static float CalcularMonto(int idFactura)
        {
            float monto = 0;
            List<Detalle_Factura> misDetallesFactura = DetallesFactura.ObtenerDetallesDeFactura(idFactura);
            foreach (Detalle_Factura item in misDetallesFactura)
            {
                monto += item.Subtotal;
            }
            return monto;
        }
        public static List<Factura> ObtenerTodosInformeFiltro(int? idCliente, float? monto, DateTime? fechaDesde, DateTime? fechaHasta)
        {
            SqlConnection conexion = null;
            List<Factura> lstFacturas = null;
            try
            {
                conexion = DB.Conectar();
                string comando = "SELECT idFactura, fechaEmision, idCliente, idEstadoFactura FROM Factura where 1=1 ";
                List<SqlParameter> lstParametros = new List<SqlParameter>();
                if (idCliente != null || idCliente > 0)
                {
                    comando += " and idCliente = @idCliente";
                    lstParametros.Add(new SqlParameter("@idCliente", idCliente));
                }
                if (fechaDesde != null && fechaHasta != null)
                {
                    comando += " and fechaEmision BETWEEN @fechaDesde AND @fechaHasta";
                    lstParametros.Add(new SqlParameter("@fechaDesde", fechaDesde));
                    lstParametros.Add(new SqlParameter("@fechaHasta", fechaHasta));
                }
                else if (fechaDesde != null)
                {
                    comando += " and fechaEmision >= @fechaDesde";
                    lstParametros.Add(new SqlParameter("@fechaDesde", fechaDesde));
                }
                else if(fechaHasta !=null)
                {
                    comando += " and fechaEmision <= @fechaHasta";
                    lstParametros.Add(new SqlParameter("@fechaHasta", fechaHasta));
                }
                SqlDataReader dr = DB.GenerarReader(comando, lstParametros, conexion);
                lstFacturas = new List<Factura>();
                Factura objFactura;
                while (dr.Read())
                {
                    objFactura = new Factura();
                    objFactura.IdFactura = (int)dr["idFactura"];
                    objFactura.FechaEmision = Convert.ToDateTime(dr["fechaEmision"]);
                    objFactura.IdCliente = Convert.ToInt32(dr["idCliente"]);
                    objFactura.IdEstadoFactura = (int)dr["idEstadoFactura"];
                    lstFacturas.Add(objFactura);
                    objFactura = null;
                }
                //conexion.Close();
            }
            catch (SqlException ex)
            {
                //Con throw la información de la pila es mas profunda de donde se genero el error
                //En la capa de Presentación se Captura como Exception
                throw new Exception("Hubo un problema al cargar las facturas.", ex);
            }
            catch (Exception ex)
            {
                throw new Exception("Hubo un problema al cargar las facturas.", ex);
            }
            finally
            {
                conexion.Close();
            }
            if (lstFacturas != null && lstFacturas.Count > 0)
            {
                float montoM = 0;
                List<Factura> lstMontoSuperado = new List<Factura>();
                foreach (Factura item in lstFacturas)
                {
                    //item.Cliente = Clientes.BuscarPorId(item.IdCliente).ObtenerNombreCompleto();
                    //item.EstadoFactura = Estados_Facturas.BuscarPorId(item.IdEstadoFactura).Nombre;
                    //item.Monto = CalcularMonto(item.IdFactura);
                    montoM = CalcularMonto(item.IdFactura);
                    if (monto ==null || montoM <= monto)
                    {
                        item.Cliente = Clientes.BuscarPorId(item.IdCliente).ObtenerNombreCompleto();
                        item.Monto = montoM;
                        item.EstadoFactura = Estados_Facturas.BuscarPorId(item.IdEstadoFactura).Nombre;
                        if (item.IdEstadoFactura != 1)
                        {
                            Detalle_Itinerario detIt = Detalles_Itinerario.BuscarFacturaInItinerario(item.IdFactura);
                            if (detIt != null)
                            {
                                item.IdItinerario = detIt.IdItinerario;
                                item.FechaReparto = detIt.FechaHoraEntrega;
                            }
                        }
                    }
                    else
                    {
                        lstMontoSuperado.Add(item);
                    }                    
                }
                eliminarFacturasMontoSuperado(lstMontoSuperado, ref lstFacturas);    
            }
            
            return lstFacturas;
        }
        private static void eliminarFacturasMontoSuperado(List<Factura> listaItemBorrar, ref List<Factura> lst)
        {
            if (listaItemBorrar!=null && listaItemBorrar.Count>0 && lst!=null && lst.Count>0)
            {
                foreach (Factura item in listaItemBorrar)
                {
                    lst.Remove(item);
                }
            }
        }
    }
}
